// Helper for bit conversions.

#include "BitHelper.h"

// Add a value of a generic type to a byte array.
template<typename T>
void BitHelper::Add(vector<char>& buffer, const T& value)
{
	const byte* bytes = static_cast<const byte*>(static_cast<const void*>(&value));
	buffer.insert(buffer.end(), bytes, bytes + sizeof(T));
}

// Add a string to a byte array.
void BitHelper::Add(vector<char>& buffer, const string& value)
{
	int length = static_cast<int>(value.length());
	Add7BitEncodedInt(buffer, length);
	const char* first = &value.at(0);
	buffer.insert(buffer.end(), first, first + length);
}

// Convert a byte array into a value of a generic type.
template<typename T>
T BitHelper::Convert(vector<char>& buffer)
{
	return *static_cast<T*>(static_cast<void*>(&buffer[0]));
}

// Convert a byte array into a string value.
string BitHelper::Convert(vector<char>& buffer)
{
	return string(buffer.begin(), buffer.end());
}

// Dummy helper to prevent LNK errors
void BitHelperLnkHelper()
{
	vector<char> buffer;
	byte val;
	BitHelper::Add(buffer, val);
	BitHelper::Convert<byte>(buffer);
	BitHelper::Convert<bool>(buffer);
	BitHelper::Convert<int>(buffer);
	BitHelper::Convert<unsigned int>(buffer);
	BitHelper::Convert<double>(buffer);
}

// Encrypt a text with a given key.
string BitHelper::Encrypt(const string& text, const unsigned int& key)
{
	const byte* bytes = static_cast<const byte*>(static_cast<const void*>(&key));
	vector<byte> keyBytes = vector<byte>(bytes, bytes + UNSIGNED_INT_SIZE);
	size_t keyLength = keyBytes.size();
	size_t textLength = text.length();
	wstring result = _W(text);
	for (int i = 0; i < textLength; i++)
		result[i] = (byte)(text.at(i) ^ keyBytes[i % keyLength]);
	return _N(result);
}

// Add a 7 bit encoded integer to a buffer.
void BitHelper::Add7BitEncodedInt(vector<char>& buffer, const int& value)
{
	unsigned int num = abs(value);

	while (num >= 128U)
	{
		buffer.push_back((char)(num | 128U));
		num >>= 7;
	}

	buffer.push_back((char)num);
}